package mpay

import org.joda.time.format.DateTimeFormatter
import org.joda.time.format.DateTimeFormat

import domain.Ozenki
import enummpay.MessageType
import nonpersisted.OzenkiRequest
import ws.TransferCode


class PaymentController {

    static allowedMethods = [save: "POST", update: "POST", delete: "POST"]

    def accountService
    def paymentService

    def ozenkiPhone = '0867760895'
    def systemAccount
//    def systemAccount = Account.findByMobile('0850102145')

    def payrequest = {
//        systemAccount = accountService.getAccountFromMobile('0850102145')
        systemAccount = Account.findByMobile('0850102145')
        String buyerMobile = params.from
        String message = params.msg
        String msg = ""

        String test = "e5099364b3cea32609a20d9f19914efb".encodeAsMD5()
        // change mobile format of buyer's mobile number
        // request from Ozenki will be +66X-XXX-XXXX
        // has to be changed to 08X-XXX-XXXX
        buyerMobile = paymentService.changeMobileFormat(buyerMobile)

        // define ozenkiResponse object
        Ozenki ozenkiResponse = new Ozenki()
        def urlOzenki
        ozenkiResponse.setUrl("192.168.192.102")
        ozenkiResponse.setRecipient(buyerMobile)
//        ozenkiResponse.setUrl("kae-router.dyndns.org")

        // check if buyer is not a member
        // then reject the request
        if (!paymentService.isExistMobile(buyerMobile)) {
            msg = "NOT MEMBER: SENDER"
            render(msg)

            // send response back to sender
            //            urlOzenki = ozenkiResponse.getSendMessageRequest(msg)
            //            redirect(url: urlOzenki)

            return
        }

        // if buyer is a member then to things below
        // create ozenki request
        OzenkiRequest mobileReq = new OzenkiRequest(message)

        // get buyer account
        def senderAccount = accountService.getAccountFromMobile(buyerMobile)

        // check valid request
        if (mobileReq.isValidRequest) {

            // check request type
            // reqeust type 999 = payment request
            if (mobileReq.getCode() == MessageType.PAYMENT) {
                println("payment request")
                String receiverMobile = mobileReq.getRequestDetail()

                // check seller phone
                // if not a mobile then reject request
                if (!paymentService.isMobile(receiverMobile)) {
                    msg = "INCORRECT MOBILE: RECEIVER"
                    render(msg)

                    //TODO: uncomment it when connecting with ozenki
                    // send response back to sender
                    //                    urlOzenki = ozenkiResponse.getSendMessageRequest(msg)
                    //                    redirect(url: urlOzenki)

                    return
                }

                // check seller phone
                // if not a member then reject request
                if (!paymentService.isExistMobile(receiverMobile)) {
                    msg = "NOT MEMBER: RECEIVER"
                    render(msg)

                    //TODO: uncomment it when connecting with ozenki
                    // send response back to sender
                    //                    urlOzenki = ozenkiResponse.getSendMessageRequest(msg)
                    //                    redirect(url: urlOzenki)

                    return
                }

                // check sender with Bank
                // if sender's account is still active in the Bank
                // at this point, both sender and receiver are members of MPay
                def receiverAccount = accountService.getAccountFromMobile(receiverMobile)
                if (!paymentService.checkAccountFromBank(senderAccount.getAccount())) {
                    msg = "BANK ACCOUNT UNAVAILABLE: SENDER"
                    render(msg)

                    //TODO: uncomment it when connecting with ozenki
                    // send response back to sender
                    //                    urlOzenki = ozenkiResponse.getSendMessageRequest(msg)
                    //                    redirect(url: urlOzenki)

                    return
                } else if (!paymentService.checkAccountFromBank(receiverAccount.getAccount())) {
                    msg = "BANK ACCOUNT UNAVAILABLE: RECEIVER"
                    render(msg)

                    //TODO: uncomment it when connecting with ozenki
                    // send response back to sender
                    //                    urlOzenki = ozenkiResponse.getSendMessageRequest(msg)
                    //                    redirect(url: urlOzenki)

                    return
                } else {
                    // if account is active
                    // should ask the sender for a pin
                    if (senderAccount.isActive && receiverAccount.isActive) {
                        // create transaction
                        def transaction = new PaymentTransaction(
                                buyerAcc: senderAccount,
                                merchantAcc: receiverAccount,
                                amount: mobileReq.getAmount(),
                                creationDate: new Date(),
                                status: "new"
                        )

                        if (transaction.save(failOnError: true, flush: true)) {
                            msg = "Please type *777*" + transaction.id + "*[YourPIN]# and send it to " + ozenkiPhone
                        } else {
                            // cannot create transaction
                            msg = "YOUR REQUEST CANNOT BE PROCESSED"
                        }

                        render(msg)

                        //TODO: uncomment it when connecting with ozenki
                        // send response back to sender
                                                urlOzenki = ozenkiResponse.getSendMessageRequest(msg)
                                                redirect(url: urlOzenki)

                        // finish validating seller mobile number
                        return
                    }

                }

            } else if (mobileReq.getCode() == MessageType.CONFIRM) {
                println("confirm request")
                // get transaction
                def transaction = PaymentTransaction.get(mobileReq.getTransactionId())

                if (transaction) {
                    String senderMobile = transaction.getBuyerAcc().getMobile()
                    Double amount = transaction.getAmount()

                    // process only a new transaction
                    if (transaction.getStatus().equals("new")) {

                        // TODO: Check PIN before check balance
                        String pin = mobileReq.getRequestDetail()
                        String encodePin = pin.encodeAsMD5()

                        // if pin is incorrect
                        // then msg = "YOUR REQUEST CANNOT BE PROCESSED: INCORRECT PIN"
                        if (!encodePin.equals(senderAccount.getPin())) {
                            msg = "YOUR REQUEST CANNOT BE PROCESSED: INCORRECT PIN"
                            render(msg)

                            //TODO: uncomment it when connecting with ozenki
                            //send response back to sender
                            //                    urlOzenki = ozenkiResponse.getSendMessageRequest(msg)
                            //                    redirect(url: urlOzenki)

                            return
                        }

                        // if pin is correct then
                        // check balance with the bank
                        if (paymentService.checkBalanceFromBank(senderAccount.getAccount(), amount)) {
                            // balance is ok
                            // then transfer money
                            TransferCode transferCode = paymentService.transferMoney(
                                    transaction.getBuyerAcc().getAccount(),     // from buyer account
                                    systemAccount.getAccount(),                 // to system account
                                    transaction.getAmount())                    // transfer amount

                            if (transferCode.code.equals("000")) {
                                // update transaction status = success
                                transaction.setStatus("success")
                                msg = "YOUR PAYMENT HAS SUCCESSFULLY PROCESSED"
                            } else {
                                // update transaction status = success
                                transaction.setStatus("error")
                                msg = "YOUR PAYMENT HAS AN ERROR: " + transferCode.getErrorMessage()
                            }

                            transaction.save(flush: true, failOnError: true)

                            msg = "Successfully paid for your products/services. Thank you for using MPay service"
                        } else {
                            // balance is not ok
                            // update transaction status = new
                            transaction.setStatus("new")
                            transaction.save(flush: true, failOnError: true)

                            // then inform sender
                            msg = "YOUR REQUEST CANNOT BE PROCESSED: Balance is deficient"
                        }

                    }

                    render(msg)

                    //TODO: uncomment it when connecting with ozenki
                    // send response back to sender
                                            urlOzenki = ozenkiResponse.getSendMessageRequest(msg)
                                            redirect(url: urlOzenki)

                    return

                } else {
                    msg = "TRANACTION NOT FOUND"
                    render(msg)

                    //TODO: uncomment it when connecting with ozenki
                    //send response back to sender
                    //                    urlOzenki = ozenkiResponse.getSendMessageRequest(msg)
                    //                    redirect(url: urlOzenki)

                    return
                }

            }

        } else {
            msg = "YOUR REQUEST IS INCORRECT"
            render(msg)

            //TODO: uncomment it when connecting with ozenki
            //send response back to sender
            //                    urlOzenki = ozenkiResponse.getSendMessageRequest(msg)
            //                    redirect(url: urlOzenki)

            return

        }


        render("OK")
        return

    }

    def listpayment = {
        String merchant = params.merchant
        String date = params.date
        println('merchant mobile: ' + merchant)
        println('date request: ' + date)

        DateTimeFormatter fm = DateTimeFormat.forPattern('yyyyMMdd')

        def merchantAcc = Account.findWhere(mobile: merchant)
        def creationDate = fm.parseDateTime(date).toDate()
        def payments = PaymentTransaction.findAllByMerchantAccAndCreationDateBetween(merchantAcc, creationDate, new Date())

        println(payments.toString())

    }

    def update = {

    }
}
